package com.tabjin.rfidsocket.service.access.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Preconditions;
import com.tabjin.rfidsocket.common.enums.CardStatusEnum;
import com.tabjin.rfidsocket.common.org.n3r.idworker.Sid;
import com.tabjin.rfidsocket.common.utils.BeanValidator;
import com.tabjin.rfidsocket.common.utils.PagedGridResult;
import com.tabjin.rfidsocket.exception.ParamException;
import com.tabjin.rfidsocket.mapper.mapper.ArchCardMapper;
import com.tabjin.rfidsocket.pojo.ArchCard;
import com.tabjin.rfidsocket.pojo.bo.access.ArchCardBO;
import com.tabjin.rfidsocket.pojo.bo.access.ArchIssueCardBO;
import com.tabjin.rfidsocket.service.access.ArchCardService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.text.ParseException;
import java.util.Date;
import java.util.List;

/**
 * @author tabjin
 * create at 2021/1/29 14:55
 * @program rfid_socket
 * @description
 */
@Service
public class ArchCardServiceImpl implements ArchCardService {

    private static Logger logger = LoggerFactory.getLogger(ArchCardServiceImpl.class);

    private final ArchCardMapper archCardMapper;
    private final Sid sid;

    public ArchCardServiceImpl(ArchCardMapper archCardMapper, Sid sid) {
        this.archCardMapper = archCardMapper;
        this.sid = sid;
    }

    /**
     * 发卡
     *
     * @param archIssueCardBO
     */
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void add(ArchIssueCardBO archIssueCardBO) {
        BeanValidator.check(archIssueCardBO);
        // 允许一人多卡，不做唯一校验
        // 卡号查重
        if (checkExist(archIssueCardBO.getCardCode())) {
            throw new ParamException("卡号重复");
        }

        ArchCard archCard = ArchCard.builder()
                // TODO 这边首先要确定用户所在项目
//                .id(sid.nextShort())
                .projectId(archIssueCardBO.getProjectId())
                .buildingId(archIssueCardBO.getBuildingId())
                .houseId(archIssueCardBO.getHouseId())
                .userId(archIssueCardBO.getUserId())
                .cardCode(archIssueCardBO.getCardCode())
                .accessAvailableStartTime(archIssueCardBO.getValidDate().get(0))
                .accessAvailableEndTime(archIssueCardBO.getValidDate().get(1))
                .status(CardStatusEnum.NORMAL.ordinal())// 发行卡是允许使用
                .type(archIssueCardBO.getCardType())
                .availableFloor(StringUtils.join(archIssueCardBO.getAvailableFloor(), ","))
                .remark(archIssueCardBO.getRemark())
                .createTime(new Date())
                .operator("张进")
                .operatorIp("127.0.0.1")
                .build();
        if (archIssueCardBO.getElevatorDate().size() > 0) {
            archCard.setElevatorAvailableStartTime(archIssueCardBO.getElevatorDate().get(0));
            archCard.setElevatorAvailableEndTime(archIssueCardBO.getElevatorDate().get(1));
        }

        archCardMapper.insertSelective(archCard);
    }

    /**
     * 删除卡片
     *
     * @param cardId
     */
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void delete(Integer cardId) {
        ArchCard before = archCardMapper.selectByPrimaryKey(cardId);
        ArchCard after = new ArchCard();
        BeanUtils.copyProperties(before, after);
        after.setDeleteTime(new Date());
        archCardMapper.updateByPrimaryKeySelective(after);
    }

    @Override
    public void delete(List<Integer> cardIdList) {

    }

    /**
     * 修改卡片
     *
     * @param archCardBO
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public ArchCard update(ArchCardBO archCardBO) {
        BeanValidator.check(archCardBO);
        ArchCard archCard = ArchCard.builder()
                .projectId(archCardBO.getProjectId())
                .buildingId(archCardBO.getBuildingId())
                .houseId(archCardBO.getHouseId())
                .userId(archCardBO.getUserId())
                .cardCode(archCardBO.getCardCode())
                .accessAvailableStartTime(archCardBO.getAccessAvailableStartTime())
                .accessAvailableEndTime(archCardBO.getAccessAvailableEndTime())
                .elevatorAvailableStartTime(archCardBO.getElevatorAvailableStartTime())
                .elevatorAvailableEndTime(archCardBO.getElevatorAvailableEndTime())
                .status(archCardBO.getStatus())
                .type(archCardBO.getType())
                .availableFloor(archCardBO.getAvailableFloor())
                .remark(archCardBO.getRemark())
                .updateTime(archCardBO.getUpdateTime())
                .operator("张进")
                .operatorIp("127.0.0.1")
                .build();

        archCardMapper.updateByPrimaryKey(archCard);
        return archCard;
    }


    @Override
    public void updateCardStatus(Integer cardId, Integer status) {
        Preconditions.checkNotNull(cardId, "卡号空");
        Preconditions.checkNotNull(status, "状态空");

//        ArchCard archCardBefore = archCardMapper.selectByPrimaryKey(cardId);
//        Preconditions.checkNotNull(archCardBefore, "未获取到卡");

        ArchCard archCard = ArchCard.builder()
                .id(cardId)
                .status(status)
                .build();

        archCardMapper.updateByPrimaryKeySelective(archCard);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public boolean hasCardByCardCode(String cardCode) {
        if (cardCode.length() != 24) {
            logger.error("卡号长度不正确");
            throw new ParamException("卡号长度不正确");
        }
        Example example = new Example(ArchCard.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("cardCode", cardCode);
        return archCardMapper.selectCountByExample(example) > 0;
    }

    /**
     * 卡片状态切换
     *
     * @param cardId
     * @param lockStatus 0 正常，1 挂失，2 禁用， 3删除
     */
    @Override
    public void lock(Integer cardId, Integer lockStatus) {
        ArchCard archCard = archCardMapper.selectByPrimaryKey(cardId);
        archCard.setStatus(lockStatus);
        archCardMapper.updateByPrimaryKey(archCard);
    }

    /**
     * 获取所有卡片
     *
     * @param page
     * @param pageSize
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public PagedGridResult getAll(Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize);

        List<ArchCard> archCardList = archCardMapper.selectAll();
        return setPagesGrid(archCardList, page);
    }

    @Override
    public ArchCard getCardByCardId(Integer cardId) {
        Preconditions.checkNotNull(cardId, "无卡片id");
        return archCardMapper.selectByPrimaryKey(cardId);
    }

    /**
     * 根据卡片id获取卡片
     *
     * @param cardIdList
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<ArchCard> getCardsByCardIds(List<Integer> cardIdList) {
        return null;
    }

    /**
     * 根据楼栋获取卡片
     *
     * @param buildingId
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<ArchCard> getCardsByBuildingId(Integer buildingId) {
        return null;
    }

    /**
     * 卡片查重
     *
     * @param cardCode
     * @return
     */
    boolean checkExist(String cardCode) {
        Example example = new Example(ArchCard.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("cardCode", cardCode);
        return archCardMapper.selectCountByExample(example) > 0;
    }

    /**
     * 封装分页助手
     *
     * @param list
     * @param page
     * @return
     */
    private PagedGridResult setPagesGrid(List<?> list, Integer page) {
        PageInfo pageList = new PageInfo<>(list);
        PagedGridResult grid = new PagedGridResult();
        grid.setPage(page);
        grid.setRows(list);
        grid.setTotal(pageList.getPages());
        grid.setRecords(pageList.getTotal());
        return grid;
    }
}
